package com.fcat.base.smartapi;


import com.fcat.base.smartapi.util.TokenUtils;

public class JFJTokenImpl implements JFJToken {
    private String keyType = "2";
    private String nKeyType = "2";
//    private String vendingKey = "5555555555555555";
    private String vendingKey = "abababababababab";
    private String nVendingKey = "5555555555555555";
    private int maxSeqNo = 230;
    private int maxTokenNum = 25;
    private int maxMonthNum = 6;
    private int decimalOffset = 5;
    private int NodecimalOffset = 80;

    public JFJTokenImpl() {
    }

    public String getCreditToken(String meterNo, String sgc, int tariffIndex, int keyVersion, int keyExpiredTime, long keyNo, int seqNo, int amount) {
        String token = "";
        String decodeKey = "";
        int res = this.CheckInputParams(meterNo, tariffIndex, keyVersion, keyExpiredTime, keyNo, seqNo, 1);
        if (res != 0) {
            return this.getRtnErrorXML(res);
        } else {
            decodeKey = TokenUtils.getDecoderKey(meterNo, Integer.toString(tariffIndex), sgc, this.vendingKey, this.keyType, Integer.toString(keyVersion));
            token = "00";
            token = token + "0100";
            token = token + TokenUtils.IntToBin((int)keyNo, 16);
            token = token + TokenUtils.IntToBin(seqNo, 8);
            token = token + TokenUtils.IntToBin(amount, 28);
            token = token + TokenUtils.CheckSum(token);
            System.err.println(token);
            token = this.getOutputToken(token, decodeKey);
            String rtnTokenXML = this.getRtnTokenXML(token);
            return rtnTokenXML;
        }
    }

    public String getKeyChangeToken(String meterNo, String sgc, int tariffIndex, int keyVersion, int keyExpiredTime, long keyNo, String nSgc, int nTariffIndex, int nKeyVersion, int nKeyExpiredTime, long nKeyNo) {
        String token = "";
        String tokenList = "";
        String decodeKey = "";
        String nDecodeKey = "";
        String nDecodeKeyBin = "";
        int res = this.CheckInputParams(meterNo, tariffIndex, keyVersion, keyExpiredTime, keyNo, 1, 1);
        if (res != 0) {
            return this.getRtnErrorXML(res);
        } else {
            res = this.CheckInputParams(meterNo, nTariffIndex, nKeyVersion, nKeyExpiredTime, nKeyNo, 1, 1);
            if (res != 0) {
                return this.getRtnErrorXML(res);
            } else {
                if (tariffIndex == 0 && keyVersion == 0 && keyExpiredTime == 0 && keyNo == 0L) {
                    decodeKey = TokenUtils.getDecoderKey(meterNo, Integer.toString(tariffIndex), "000000", this.vendingKey, this.keyType, Integer.toString(keyVersion));
                } else {
                    decodeKey = TokenUtils.getDecoderKey(meterNo, Integer.toString(tariffIndex), sgc, this.vendingKey, this.keyType, Integer.toString(keyVersion));
                }

                nDecodeKey = TokenUtils.getDecoderKey(meterNo, Integer.toString(nTariffIndex), nSgc, this.nVendingKey, this.nKeyType, Integer.toString(nKeyVersion));
                nDecodeKeyBin = TokenUtils.HexToBin(nDecodeKey, 64);
                token = "10";
                token = token + "0011";
                token = token + "0";
                token = token + "0";
                token = token + TokenUtils.IntToBin(Integer.parseInt(this.nKeyType), 2);
                token = token + TokenUtils.IntToBin((int)nKeyNo, 16);
                token = token + TokenUtils.substring(nDecodeKeyBin, 0, 32);
                token = token + TokenUtils.CheckSum(token);
                token = this.getOutputToken(token, decodeKey);
                tokenList = tokenList + ',' + token;
                token = "10";
                token = token + "0100";
                token = token + TokenUtils.IntToBin(nKeyExpiredTime, 8);
                token = token + TokenUtils.IntToBin(nKeyVersion, 4);
                token = token + TokenUtils.IntToBin(nTariffIndex, 8);
                token = token + TokenUtils.substring(nDecodeKeyBin, 32, 32);
                token = token + TokenUtils.CheckSum(token);
                token = this.getOutputToken(token, decodeKey);
                tokenList = tokenList + ',' + token;
                String rtnTokenXML = this.getRtnTokenXML(tokenList);
                return rtnTokenXML;
            }
        }
    }

    public String getClearBalanceToken(String meterNo, String sgc, int tariffIndex, int keyVersion, int keyExpiredTime, long keyNo, int seqNo) {
        String token = "";
        String decodeKey = "";
        int res = this.CheckInputParams(meterNo, tariffIndex, keyVersion, keyExpiredTime, keyNo, seqNo, 1);
        if (res != 0) {
            return this.getRtnErrorXML(res);
        } else {
            decodeKey = TokenUtils.getDecoderKey(meterNo, Integer.toString(tariffIndex), sgc, this.vendingKey, this.keyType, Integer.toString(keyVersion));
            token = "10";
            token = token + "0001";
            token = token + TokenUtils.IntToBin((int)keyNo, 16);
            token = token + TokenUtils.IntToBin(seqNo, 8);
            token = token + TokenUtils.IntToBin(0, 28);
            token = token + TokenUtils.CheckSum(token);
            token = this.getOutputToken(token, decodeKey);
            String rtnTokenXML = this.getRtnTokenXML(token);
            return rtnTokenXML;
        }
    }

    public String getClearEventToken(String meterNo, String sgc, int tariffIndex, int keyVersion, int keyExpiredTime, long keyNo, int seqNo) {
        String token = "";
        String decodeKey = "";
        int res = this.CheckInputParams(meterNo, tariffIndex, keyVersion, keyExpiredTime, keyNo, seqNo, 1);
        if (res != 0) {
            return this.getRtnErrorXML(res);
        } else {
            decodeKey = TokenUtils.getDecoderKey(meterNo, Integer.toString(tariffIndex), sgc, this.vendingKey, this.keyType, Integer.toString(keyVersion));
            token = "10";
            token = token + "0101";
            token = token + TokenUtils.IntToBin((int)keyNo, 16);
            token = token + TokenUtils.IntToBin(seqNo, 8);
            token = token + TokenUtils.IntToBin(0, 28);
            token = token + TokenUtils.CheckSum(token);
            token = this.getOutputToken(token, decodeKey);
            String rtnTokenXML = this.getRtnTokenXML(token);
            return rtnTokenXML;
        }
    }

    public String getTestToken(int manufacturingID, int control) {
        String token = "";
        String controlBin = "";
        if (control < 0 || control > 36) {
            control = 0;
        }

        while(controlBin.length() < control) {
            controlBin = "0" + controlBin;
        }

        for(controlBin = "1" + controlBin; controlBin.length() < 36; controlBin = "0" + controlBin) {
        }

        token = "01";
        token = token + "1011";
        token = token + controlBin;
        token = token + TokenUtils.IntToBin(manufacturingID, 16);
        token = token + TokenUtils.CheckSum(token);
        char char_00 = token.charAt(0);
        char char_01 = token.charAt(1);
        token = TokenUtils.substring(token, 2, 64);
        char char_35 = token.charAt(35);
        char char_36 = token.charAt(36);
        token = token.substring(0, 35) + String.valueOf(char_00) + char_01 + token.substring(37, 64);
        token = String.valueOf(char_35) + String.valueOf(char_36) + token;

        for(token = TokenUtils.BinToDec(token); token.length() < 20; token = "0" + token) {
        }

        String rtnTokenXML = this.getRtnTokenXML(token);
        return rtnTokenXML;
    }

    public String getMaxPowerLimitToken(String meterNo, String sgc, int tariffIndex, int keyVersion, int keyExpiredTime, long keyNo, int seqNo, int activatingModel, String activatingDate, int[] maxPowerLimits, int[] hours) {
        String token = "";
        String tokenList = "";
        String decodeKey = "";
        int res = this.CheckInputParams(meterNo, tariffIndex, keyVersion, keyExpiredTime, keyNo, seqNo, 1);
        if (res != 0) {
            return this.getRtnErrorXML(res);
        } else if (seqNo + 2 > this.maxSeqNo) {
            return this.getRtnErrorXML(1);
        } else {
            decodeKey = TokenUtils.getDecoderKey(meterNo, Integer.toString(tariffIndex), sgc, this.vendingKey, this.keyType, Integer.toString(keyVersion));
            token = "11";
            token = token + "0101";
            token = token + TokenUtils.IntToBin((int)keyNo, 16);
            token = token + TokenUtils.IntToBin(seqNo, 8);
            token = token + TokenUtils.IntToBin(0, 8);
            token = token + TokenUtils.IntToBin(maxPowerLimits[0], 12);
            token = token + this.getHourBin(hours[0]);
            token = token + TokenUtils.CheckSum(token);
            token = this.getOutputToken(token, decodeKey);
            tokenList = tokenList + ',' + token;
            ++seqNo;
            token = "11";
            token = token + "0101";
            token = token + TokenUtils.IntToBin((int)keyNo, 16);
            token = token + TokenUtils.IntToBin(seqNo, 8);
            token = token + TokenUtils.IntToBin(1, 8);
            token = token + TokenUtils.IntToBin(maxPowerLimits[1], 12);
            token = token + this.getHourBin(hours[1]);
            token = token + TokenUtils.CheckSum(token);
            token = this.getOutputToken(token, decodeKey);
            tokenList = tokenList + ',' + token;
            ++seqNo;
            String activateDateBin = this.getDateBin(activatingDate);
            token = "11";
            token = token + "0100";
            token = token + TokenUtils.IntToBin((int)keyNo, 16);
            token = token + TokenUtils.IntToBin(seqNo, 8);
            token = token + TokenUtils.IntToBin(0, 3);
            token = token + TokenUtils.IntToBin(activatingModel, 1);
            token = token + TokenUtils.IntToBin(0, 4);
            token = token + activateDateBin;
            token = token + TokenUtils.CheckSum(token);
            token = this.getOutputToken(token, decodeKey);
            tokenList = tokenList + ',' + token;
            String rtnTokenXML = this.getRtnTokenXML(tokenList);
            return rtnTokenXML;
        }
    }

    public String getSingleTariffToken(String meterNo, String sgc, int tariffIndex, int keyVersion, int keyExpiredTime, long keyNo, int seqNo, String activatingDate, int activatingModel, int validDate, int rate) {
        String token = "";
        String tokenList = "";
        String decodeKey = "";
        int res = this.CheckInputParams(meterNo, tariffIndex, keyVersion, keyExpiredTime, keyNo, seqNo, 1);
        if (res != 0) {
            return this.getRtnErrorXML(res);
        } else if (seqNo + 1 > this.maxSeqNo) {
            return this.getRtnErrorXML(1);
        } else {
            decodeKey = TokenUtils.getDecoderKey(meterNo, Integer.toString(tariffIndex), sgc, this.vendingKey, this.keyType, Integer.toString(keyVersion));
            token = "11";
            token = token + "0110";
            token = token + TokenUtils.IntToBin((int)keyNo, 16);
            token = token + TokenUtils.IntToBin(seqNo, 8);
            token = token + TokenUtils.IntToBin(0, 14);
            token = token + TokenUtils.IntToBin(rate, 14);
            token = token + TokenUtils.CheckSum(token);
            token = this.getOutputToken(token, decodeKey);
            tokenList = tokenList + ',' + token;
            ++seqNo;
            String activateDateBin = this.getDateBin(activatingDate);
            token = "11";
            token = token + "0100";
            token = token + TokenUtils.IntToBin((int)keyNo, 16);
            token = token + TokenUtils.IntToBin(seqNo, 8);
            token = token + TokenUtils.IntToBin(1, 3);
            token = token + TokenUtils.IntToBin(activatingModel, 1);
            token = token + TokenUtils.IntToBin(validDate, 4);
            token = token + activateDateBin;
            token = token + TokenUtils.CheckSum(token);
            token = this.getOutputToken(token, decodeKey);
            tokenList = tokenList + ',' + token;
            String rtnTokenXML = this.getRtnTokenXML(tokenList);
            return rtnTokenXML;
        }
    }

    public String getStepTariffToken(String meterNo, String sgc, int tariffIndex, int keyVersion, int keyExpiredTime, long keyNo, int seqNo, String activatingDate, int activatingModel, int validDate, int[] rates, int[] steps) {
        String token = "";
        String tokenList = "";
        String decodeKey = "";
        int res = this.CheckInputParams(meterNo, tariffIndex, keyVersion, keyExpiredTime, keyNo, seqNo, 1);
        if (res != 0) {
            return this.getRtnErrorXML(res);
        } else {
            int rateNum = 0;

            int i;
            for(i = 0; i <= rates.length - 1 && rates[i] != 0; ++i) {
                ++rateNum;
            }

            if (seqNo + rateNum > this.maxSeqNo) {
                return this.getRtnErrorXML(1);
            } else {
                decodeKey = TokenUtils.getDecoderKey(meterNo, Integer.toString(tariffIndex), sgc, this.vendingKey, this.keyType, Integer.toString(keyVersion));
                --seqNo;

                for(i = 0; i <= rateNum - 1; ++i) {
                    ++seqNo;
                    token = "11";
                    if (i >= 8) {
                        token = token + "1001";
                    } else if (i >= 4) {
                        token = token + "1000";
                    } else {
                        token = token + "0111";
                    }

                    token = token + TokenUtils.IntToBin((int)keyNo, 16);
                    token = token + TokenUtils.IntToBin(seqNo, 8);
                    token = token + TokenUtils.IntToBin(i % 4, 2);
                    if (i == rateNum - 1) {
                        token = token + TokenUtils.IntToBin(0, 13);
                    } else {
                        token = token + TokenUtils.IntToBin(steps[i], 13);
                    }

                    token = token + TokenUtils.IntToBin(rates[i], 13);
                    token = token + TokenUtils.CheckSum(token);
                    token = this.getOutputToken(token, decodeKey);
                    tokenList = tokenList + ',' + token;
                }

                ++seqNo;
                String activateDateBin = this.getDateBin(activatingDate);
                token = "11";
                token = token + "0100";
                token = token + TokenUtils.IntToBin((int)keyNo, 16);
                token = token + TokenUtils.IntToBin(seqNo, 8);
                token = token + TokenUtils.IntToBin(2, 3);
                token = token + TokenUtils.IntToBin(activatingModel, 1);
                token = token + TokenUtils.IntToBin(validDate, 4);
                token = token + activateDateBin;
                token = token + TokenUtils.CheckSum(token);
                token = this.getOutputToken(token, decodeKey);
                tokenList = tokenList + ',' + token;
                String rtnTokenXML = this.getRtnTokenXML(tokenList);
                return rtnTokenXML;
            }
        }
    }

    public String getTOUTariffToken(String meterNo, String sgc, int tariffIndex, int keyVersion, int keyExpiredTime, long keyNo, int seqNo, String activatingDate, int activatingModel, int validDate, int[] rates, int[] times) {
        String token = "";
        String tokenList = "";
        String decodeKey = "";
        int res = this.CheckInputParams(meterNo, tariffIndex, keyVersion, keyExpiredTime, keyNo, seqNo, 1);
        if (res != 0) {
            return this.getRtnErrorXML(res);
        } else {
            int rateNum = 0;

            int i;
            for(i = 0; i <= rates.length - 1 && rates[i] != 0; ++i) {
                ++rateNum;
            }

            if (seqNo + rateNum > this.maxSeqNo) {
                return this.getRtnErrorXML(1);
            } else {
                decodeKey = TokenUtils.getDecoderKey(meterNo, Integer.toString(tariffIndex), sgc, this.vendingKey, this.keyType, Integer.toString(keyVersion));
                --seqNo;

                for(i = 0; i <= rateNum - 1; ++i) {
                    ++seqNo;
                    token = "11";
                    token = token + "1010";
                    token = token + TokenUtils.IntToBin((int)keyNo, 16);
                    token = token + TokenUtils.IntToBin(seqNo, 8);
                    token = token + TokenUtils.IntToBin(i, 6);
                    token = token + TokenUtils.IntToBin(rates[i], 14);
                    token = token + this.getHourBin(times[i]);
                    token = token + TokenUtils.CheckSum(token);
                    token = this.getOutputToken(token, decodeKey);
                    tokenList = tokenList + ',' + token;
                }

                ++seqNo;
                String activateDateBin = this.getDateBin(activatingDate);
                token = "11";
                token = token + "0100";
                token = token + TokenUtils.IntToBin((int)keyNo, 16);
                token = token + TokenUtils.IntToBin(seqNo, 8);
                token = token + TokenUtils.IntToBin(3, 3);
                token = token + TokenUtils.IntToBin(activatingModel, 1);
                token = token + TokenUtils.IntToBin(validDate, 4);
                token = token + activateDateBin;
                token = token + TokenUtils.CheckSum(token);
                token = this.getOutputToken(token, decodeKey);
                tokenList = tokenList + ',' + token;
                String rtnTokenXML = this.getRtnTokenXML(tokenList);
                return rtnTokenXML;
            }
        }
    }

    public String getFriendModeToken(String meterNo, String sgc, int tariffIndex, int keyVersion, int keyExpiredTime, long keyNo, int seqNo, int friendMode, int[] times, int[] days, int N_of_allowable_days) {
        String token = "";
        String weekendBin = "";
        String hoursBin = "";
        String decodeKey = "";
        int res = this.CheckInputParams(meterNo, tariffIndex, keyVersion, keyExpiredTime, keyNo, seqNo, 1);
        if (res != 0) {
            return this.getRtnErrorXML(res);
        } else {
            decodeKey = TokenUtils.getDecoderKey(meterNo, Integer.toString(tariffIndex), sgc, this.vendingKey, this.keyType, Integer.toString(keyVersion));

            for(int i = 0; i <= days.length - 1; ++i) {
                weekendBin = weekendBin + Integer.toString(days[i]);
            }

            while(weekendBin.length() < 7) {
                weekendBin = weekendBin + "1";
            }

            weekendBin = weekendBin.substring(0, 7);
            hoursBin = this.getShortHourBin(times[0]) + this.getShortHourBin(times[1]);
            token = "11";
            token = token + "0000";
            token = token + TokenUtils.IntToBin((int)keyNo, 16);
            token = token + TokenUtils.IntToBin(seqNo, 8);
            token = token + TokenUtils.IntToBin(friendMode, 1);
            token = token + weekendBin;
            token = token + hoursBin;
            token = token + TokenUtils.IntToBin(N_of_allowable_days, 8);
            token = token + TokenUtils.CheckSum(token);
            token = this.getOutputToken(token, decodeKey);
            String rtnTokenXML = this.getRtnTokenXML(token);
            return rtnTokenXML;
        }
    }

    public String getChangeMeterModeToken(String meterNo, String sgc, int tariffIndex, int keyVersion, int keyExpiredTime, long keyNo, int seqNo, int mode) {
        String token = "";
        String decodeKey = "";
        int res = this.CheckInputParams(meterNo, tariffIndex, keyVersion, keyExpiredTime, keyNo, seqNo, 1);
        if (res != 0) {
            return this.getRtnErrorXML(res);
        } else {
            decodeKey = TokenUtils.getDecoderKey(meterNo, Integer.toString(tariffIndex), sgc, this.vendingKey, this.keyType, Integer.toString(keyVersion));
            token = "11";
            token = token + "0001";
            token = token + TokenUtils.IntToBin((int)keyNo, 16);
            token = token + TokenUtils.IntToBin(seqNo, 8);
            token = token + TokenUtils.IntToBin(0, 20);
            token = token + TokenUtils.IntToBin(mode, 8);
            token = token + TokenUtils.CheckSum(token);
            token = this.getOutputToken(token, decodeKey);
            String rtnTokenXML = this.getRtnTokenXML(token);
            return rtnTokenXML;
        }
    }

    public String getSetCreditAmountLimitOrOverdrawAmountLimitToken(String meterNo, String sgc, int tariffIndex, int keyVersion, int keyExpiredTime, long keyNo, int seqNo, int amountType, int amountLimit) {
        String token = "";
        String decodeKey = "";
        int res = this.CheckInputParams(meterNo, tariffIndex, keyVersion, keyExpiredTime, keyNo, seqNo, 1);
        if (res != 0) {
            return this.getRtnErrorXML(res);
        } else {
            decodeKey = TokenUtils.getDecoderKey(meterNo, Integer.toString(tariffIndex), sgc, this.vendingKey, this.keyType, Integer.toString(keyVersion));
            token = "11";
            if (amountType == 0) {
                token = token + "0011";
            } else {
                token = token + "0010";
            }

            token = token + TokenUtils.IntToBin((int)keyNo, 16);
            token = token + TokenUtils.IntToBin(seqNo, 8);
            token = token + TokenUtils.IntToBin(amountLimit, 28);
            token = token + TokenUtils.CheckSum(token);
            token = this.getOutputToken(token, decodeKey);
            String rtnTokenXML = this.getRtnTokenXML(token);
            return rtnTokenXML;
        }
    }

    public String SetLowCreditWarningLimitToken(String meterNo, String sgc, int tariffIndex, int keyVersion, int keyExpiredTime, long keyNo, int seqNo, int amountType, int amountLimit) {
        String token = "";
        String decodeKey = "";
        int res = this.CheckInputParams(meterNo, tariffIndex, keyVersion, keyExpiredTime, keyNo, seqNo, 1);
        if (res != 0) {
            return this.getRtnErrorXML(res);
        } else {
            decodeKey = TokenUtils.getDecoderKey(meterNo, Integer.toString(tariffIndex), sgc, this.vendingKey, this.keyType, Integer.toString(keyVersion));
            token = "11";
            token = token + "1110";
            token = token + TokenUtils.IntToBin((int)keyNo, 16);
            token = token + TokenUtils.IntToBin(seqNo, 8);
            token = token + "0000";
            token = token + TokenUtils.IntToBin(amountLimit, 24);
            token = token + TokenUtils.CheckSum(token);
            token = this.getOutputToken(token, decodeKey);
            String rtnTokenXML = this.getRtnTokenXML(token);
            return rtnTokenXML;
        }
    }

    public String getLogoffToken(String meterNo, String sgc, int tariffIndex, int keyVersion, int keyExpiredTime, long keyNo, int seqNo) {
        String token = "";
        String decodeKey = "";
        int res = this.CheckInputParams(meterNo, tariffIndex, keyVersion, keyExpiredTime, keyNo, seqNo, 1);
        if (res != 0) {
            return this.getRtnErrorXML(res);
        } else {
            decodeKey = TokenUtils.getDecoderKey(meterNo, Integer.toString(tariffIndex), sgc, this.vendingKey, this.keyType, Integer.toString(keyVersion));
            token = "11";
            token = token + "1101";
            token = token + TokenUtils.IntToBin((int)keyNo, 16);
            token = token + TokenUtils.IntToBin(seqNo, 8);
            token = token + TokenUtils.IntToBin(0, 28);
            token = token + TokenUtils.CheckSum(token);
            token = this.getOutputToken(token, decodeKey);
            String rtnTokenXML = this.getRtnTokenXML(token);
            return rtnTokenXML;
        }
    }

    public String getFriendHolidayToken(String meterNo, String sgc, int tariffIndex, int keyVersion, int keyExpiredTime, long keyNo, int seqNo, int holidayMode, String[] holidays) {
        String token = "";
        String tokenList = "";
        String holiday = "";
        String holidayBin = "";
        String decodeKey = "";
        int res = this.CheckInputParams(meterNo, tariffIndex, keyVersion, keyExpiredTime, keyNo, seqNo, 1);
        if (res != 0) {
            return this.getRtnErrorXML(res);
        } else {
            int holidayNum = 0;

            int i;
            for(i = 0; i <= holidays.length - 1 && !holidays[i].isEmpty(); ++i) {
                ++holidayNum;
            }

            if (seqNo + holidayNum - 1 > this.maxSeqNo) {
                return this.getRtnErrorXML(1);
            } else {
                decodeKey = TokenUtils.getDecoderKey(meterNo, Integer.toString(tariffIndex), sgc, this.vendingKey, this.keyType, Integer.toString(keyVersion));

                for(i = 0; i <= holidayNum - 1; ++i) {
                    if (i != 0) {
                        ++seqNo;
                    }

                    holiday = holidays[i];
                    if (holiday.length() == 5) {
                        holiday = "0000-" + holiday;
                    }

                    holidayBin = this.getDateBin(holiday);
                    token = "11";
                    token = token + "1100";
                    token = token + TokenUtils.IntToBin((int)keyNo, 16);
                    token = token + TokenUtils.IntToBin(seqNo, 8);
                    token = token + TokenUtils.IntToBin(i + 1, 7);
                    token = token + TokenUtils.IntToBin(holidayMode, 1);
                    token = token + holidayBin;
                    token = token + TokenUtils.CheckSum(token);
                    token = this.getOutputToken(token, decodeKey);
                    tokenList = tokenList + ',' + token;
                }

                String rtnTokenXML = this.getRtnTokenXML(tokenList);
                return rtnTokenXML;
            }
        }
    }

    public String getReturnToken(String meterNo, String sgc, int tariffIndex, int keyVersion, int keyExpiredTime, long keyNo, String Token) {
        String tokenData = "";
        String tokenBin = "";
        String decodeKey = "";
        int csOffset = 0;
        int res = this.CheckInputParams(meterNo, tariffIndex, keyVersion, keyExpiredTime, keyNo, 1, 1);
        if (res != 0) {
            return this.getRtnErrorXML(res);
        } else {
            decodeKey = TokenUtils.getDecoderKey(meterNo, Integer.toString(tariffIndex), sgc, this.vendingKey, this.keyType, Integer.toString(keyVersion));
            tokenBin = TokenUtils.BigIntToBin(Token, 66);
            char char_35 = tokenBin.charAt(0);
            char char_36 = tokenBin.charAt(1);
            tokenBin = tokenBin.substring(2, tokenBin.length());
            char char_00 = tokenBin.charAt(35);
            char char_01 = tokenBin.charAt(36);
            tokenBin = tokenBin.substring(0, 35) + String.valueOf(char_35) + char_36 + tokenBin.substring(37, 64);
            tokenData = TokenUtils.BinToHex(tokenBin, 16);
            tokenData = TokenUtils.FDecryptionAlgorithm07(tokenData, decodeKey);
            tokenBin = TokenUtils.HexToBin(tokenData, 64);
            String originalTokenBin = String.valueOf(char_00) + String.valueOf(char_01) + tokenBin.substring(0, 56);
            if (TokenUtils.getRtnTokenCheckSum(originalTokenBin, this.decimalOffset).compareTo(tokenBin.substring(56, 64)) == 0) {
                csOffset = this.decimalOffset;
            } else {
                if (TokenUtils.getRtnTokenCheckSum(originalTokenBin, this.NodecimalOffset).compareTo(tokenBin.substring(56, 64)) != 0) {
                    return "";
                }

                csOffset = this.NodecimalOffset;
            }

            String rtnTokenXML = this.getAnalsyeRtnTokenXML(originalTokenBin, csOffset);
            return rtnTokenXML;
        }
    }

    private int CheckInputParams(String meterNo, int tarrifIndex, int keyVersion, int keyExpiredTime, long keyNo, int seqNo, int amount) {
        if (seqNo >= 0 && seqNo <= this.maxSeqNo) {
            if (tarrifIndex >= 0 && tarrifIndex <= 99) {
                if (keyVersion >= 0 && keyVersion <= 9) {
                    if (keyExpiredTime >= 0 && keyExpiredTime <= 255) {
                        if (keyNo >= 0L && keyNo <= 65535L) {
                            if (meterNo != null && meterNo.length() > 0 && meterNo.length() <= 16) {
                                return amount >= 1 && amount <= 99999999 ? 0 : 7;
                            } else {
                                return 6;
                            }
                        } else {
                            return 5;
                        }
                    } else {
                        return 4;
                    }
                } else {
                    return 3;
                }
            } else {
                return 2;
            }
        } else {
            return 1;
        }
    }

    private String getOutputToken(String tokenBin, String decodeKey) {
        String token = "";
        String tokenData = "";
        char char_00 = tokenBin.charAt(0);
        char char_01 = tokenBin.charAt(1);
        tokenBin = TokenUtils.substring(tokenBin, 2, 64);
        tokenData = TokenUtils.BinToHex(tokenBin, 16);
        System.err.println("tokenData:  " + tokenData);
        System.err.println("decodeKey:  " + decodeKey);
        tokenData = TokenUtils.FEncryptionAlgorithm07(tokenData, decodeKey);
        tokenBin = TokenUtils.HexToBin(tokenData, 64);
        char char_35 = tokenBin.charAt(35);
        char char_36 = tokenBin.charAt(36);
        tokenBin = tokenBin.substring(0, 35) + String.valueOf(char_00) + char_01 + tokenBin.substring(37, 64);
        tokenBin = String.valueOf(char_35) + String.valueOf(char_36) + tokenBin;

        for(token = TokenUtils.BinToDec(tokenBin); token.length() < 20; token = "0" + token) {
        }

        return token;
    }

    private String formatTokenWithSpace(String token) {
        String result = "";
        token = token.replace(" ", "");
        result = TokenUtils.substring(token, 0, 4) + " ";
        result = result + TokenUtils.substring(token, 4, 4) + " ";
        result = result + TokenUtils.substring(token, 8, 4) + " ";
        result = result + TokenUtils.substring(token, 12, 4) + " ";
        result = result + TokenUtils.substring(token, 16, 4);
        return result;
    }

    private String getHourBin(Integer hour) {
        String sHour = "";
        String hourBin = "";

        for(sHour = hour.toString(); sHour.length() < 2; sHour = "0" + sHour) {
        }

        hourBin = TokenUtils.IntToBin(Integer.parseInt(sHour.substring(0, 1)), 4) + TokenUtils.IntToBin(Integer.parseInt(sHour.substring(1, 2)), 4);
        return hourBin;
    }

    private String getShortHourBin(Integer hour) {
        String sHour = "";
        String hourBin = "";

        for(sHour = hour.toString(); sHour.length() < 2; sHour = "0" + sHour) {
        }

        hourBin = TokenUtils.IntToBin(Integer.parseInt(sHour.substring(0, 1)), 2) + TokenUtils.IntToBin(Integer.parseInt(sHour.substring(1, 2)), 4);
        return hourBin;
    }

    private String getDateBin(String Date) {
        String date = Date.replace("-", "");
        String dateBin = TokenUtils.IntToBin(Integer.parseInt(TokenUtils.substring(date, 2, 1), 16), 4) + TokenUtils.IntToBin(Integer.parseInt(TokenUtils.substring(date, 3, 1), 16), 4) + TokenUtils.IntToBin(Integer.parseInt(TokenUtils.substring(date, 4, 1)), 2) + TokenUtils.IntToBin(Integer.parseInt(TokenUtils.substring(date, 5, 1)), 4) + TokenUtils.IntToBin(Integer.parseInt(TokenUtils.substring(date, 6, 1)), 2) + TokenUtils.IntToBin(Integer.parseInt(TokenUtils.substring(date, 7, 1)), 4);
        return dateBin;
    }

    private String getRtnErrorXML(int error) {
        String result = "";
        result = result + "<?xml version=\"1.0\" encoding=\"UTF-8\"?>";
        result = result + "<result>";
        result = result + "<errorCode>" + error + "</errorCode>";
        result = result + "</result>";
        return result;
    }

    private String getRtnTokenXML(String tokenList) {
        String result = "";
        String token = "";
        if (tokenList.charAt(0) == ',') {
            tokenList = tokenList.substring(1, tokenList.length());
        }

        result = result + "<?xml version=\"1.0\" encoding=\"UTF-8\"?>";
        result = result + "<result>";
        result = result + "<errorCode>0</errorCode>";

        Integer pos;
        for(result = result + "<tokens>"; tokenList.indexOf(",") > -1; tokenList = tokenList.substring(pos + 1, tokenList.length())) {
            pos = tokenList.indexOf(",");
            token = TokenUtils.substring(tokenList, 0, pos);
            token = this.formatTokenWithSpace(token);
            result = result + "<token>";
            result = result + token;
            result = result + "</token>";
        }

        token = this.formatTokenWithSpace(tokenList);
        result = result + "<token>";
        result = result + token;
        result = result + "</token>";
        result = result + "</tokens>";
        result = result + "</result>";
        return result;
    }

    private String getAnalsyeRtnTokenXML(String tokenBin, int csOffset) {
        String result = "";
        String tokenType = "";
        String balance = "";
        String seqNo = "";
        String clockSetFlag = "0";
        String batteryVoltageLowFlag = "0";
        String openCoverFlag = "0";
        String openBottomCoverFlag = "0";
        String byPassFlag = "0";
        String reverseFlag = "0";
        String magneticInterfereFlag = "0";
        String relayStatusFlag = "0";
        String relayFaultFlag = "0";
        String overdraftUsedFlag = "0";
        String forwardActiveEnergyTol = "0";
        String dataBin = "";
        dataBin = tokenBin.substring(0, 2);
        if (dataBin.compareTo("00") == 0) {
            tokenType = "0";
        } else if (dataBin.compareTo("01") == 0) {
            tokenType = "1";
        }

        dataBin = tokenBin.substring(2, 10);
        seqNo = TokenUtils.BinToDec(dataBin);
        dataBin = tokenBin.substring(10, 20);
        if (String.valueOf(dataBin.charAt(9)).compareTo("1") == 0) {
            clockSetFlag = "1";
        }

        if (String.valueOf(dataBin.charAt(8)).compareTo("1") == 0) {
            batteryVoltageLowFlag = "1";
        }

        if (String.valueOf(dataBin.charAt(7)).compareTo("1") == 0) {
            openCoverFlag = "1";
        }

        if (String.valueOf(dataBin.charAt(6)).compareTo("1") == 0) {
            openBottomCoverFlag = "1";
        }

        if (String.valueOf(dataBin.charAt(5)).compareTo("1") == 0) {
            byPassFlag = "1";
        }

        if (String.valueOf(dataBin.charAt(4)).compareTo("1") == 0) {
            reverseFlag = "1";
        }

        if (String.valueOf(dataBin.charAt(3)).compareTo("1") == 0) {
            magneticInterfereFlag = "1";
        }

        if (String.valueOf(dataBin.charAt(2)).compareTo("1") == 0) {
            relayStatusFlag = "1";
        }

        if (String.valueOf(dataBin.charAt(1)).compareTo("1") == 0) {
            relayFaultFlag = "1";
        }

        if (String.valueOf(dataBin.charAt(0)).compareTo("1") == 0) {
            overdraftUsedFlag = "1";
        }

        dataBin = tokenBin.substring(20, 38);
        balance = TokenUtils.BinToDec(dataBin);
        if (csOffset == this.decimalOffset) {
            balance = Double.toString(Double.parseDouble(balance) / 10.0D);
        }

        dataBin = tokenBin.substring(38, 58);
        forwardActiveEnergyTol = TokenUtils.BinToDec(dataBin);
        if (csOffset == this.decimalOffset) {
            forwardActiveEnergyTol = Double.toString(Double.parseDouble(forwardActiveEnergyTol) / 10.0D);
        }

        result = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>";
        result = result + "<result>";
        result = result + "<type>" + tokenType + "</type>";
        result = result + "<balance>" + balance + "</balance>";
        result = result + "<sequence>" + seqNo + "</sequence>";
        result = result + "<event>";
        result = result + "<clockSetFlag>" + clockSetFlag + "</clockSetFlag>";
        result = result + "<batteryVoltageLowFlag>" + batteryVoltageLowFlag + "</batteryVoltageLowFlag>";
        result = result + "<openCoverFlag>" + openCoverFlag + "</openCoverFlag>";
        result = result + "<openBottomCoverFlag>" + openBottomCoverFlag + "</openBottomCoverFlag>";
        result = result + "<byPassFlag>" + byPassFlag + "</byPassFlag>";
        result = result + "<reverseFlag>" + reverseFlag + "</reverseFlag>";
        result = result + "<magneticInterfereFlag>" + magneticInterfereFlag + "</magneticInterfereFlag>";
        result = result + "<relayStatusFlag>" + relayStatusFlag + "</relayStatusFlag>";
        result = result + "<relayFaultFlag>" + relayFaultFlag + "</relayFaultFlag>";
        result = result + "<overdraftUsedFlag>" + overdraftUsedFlag + "</overdraftUsedFlag>";
        result = result + "<forwardActiveEnergyTol>" + forwardActiveEnergyTol + "</forwardActiveEnergyTol>";
        result = result + "<tariffIndex>" + "0" + "</tariffIndex>";
        result = result + "</event>";
        result = result + "</result>";
        return result;
    }

    public String encryptSmartCardReturnData(int answerToReset, int binaryPattern, int version, String meterID, String customerID, String utilityID, long sanctionedLoad, int meterType, int lastRechargeAmount, String lastRechargeDate, String lastTransactionID, String cardType, String pwdData, int TokenTotalNumber, String[] tokens) {
        String cardMap = "";
        String block1 = "";
        String block2 = "";
        String block3 = "";
        String block4 = "";
        String block5 = "";
        String block6 = "";
        String block7 = "";
        String block8 = "";
        String block9 = "";
        String monthData = "";
        String eventData = "";
        String checkSum = "";
        String blankAreaData = "";
        block1 = "";
        block1 = block1 + TokenUtils.FillData(Long.toString((long)answerToReset), "0", 8);
        block1 = block1 + TokenUtils.FillData(Long.toHexString((long)binaryPattern), "0", 4);
        block1 = block1 + TokenUtils.ReverseData(Long.toString((long)version), 2);
        block1 = block1 + TokenUtils.ReverseData(meterID, 20);
        block1 = block1 + TokenUtils.ReverseData(customerID, 20);
        block1 = block1 + TokenUtils.ReverseData(utilityID, 12);
        block1 = block1 + TokenUtils.ReverseData(Long.toString(sanctionedLoad), 12);
        block1 = block1 + TokenUtils.ReverseData(Long.toHexString((long)meterType), 2);
        block1 = block1 + TokenUtils.FillData("", "F", 4);
        block1 = block1 + TokenUtils.ReverseData(Long.toHexString((long)lastRechargeAmount), 8);
        block1 = block1 + TokenUtils.ReverseData(lastRechargeDate, 6);
        block1 = block1 + TokenUtils.FillData(lastTransactionID, "0", 20);
        blankAreaData = TokenUtils.FillData("", "F", 82);
        block2 = "";
        block2 = block2 + TokenUtils.ReverseData(cardType, 4);
        block2 = block2 + "FF";
        block2 = block2 + TokenUtils.ReverseData(Long.toHexString((long)TokenTotalNumber), 2);
        checkSum = TokenUtils.getCheckSum(block2);
        checkSum = TokenUtils.ReverseData(checkSum, 4);
        block2 = blankAreaData + block2 + checkSum;
        blankAreaData = TokenUtils.FillData("", "F", 12);
        block3 = "";

        int i;
        for(i = 0; i <= TokenTotalNumber - 1; ++i) {
            block3 = block3 + TokenUtils.FillData(tokens[i], "F", 20);
        }

        for(i = TokenTotalNumber; i <= this.maxTokenNum - 1; ++i) {
            block3 = block3 + TokenUtils.FillData("", "F", 20);
        }

        block3 = blankAreaData + block3;
        blankAreaData = TokenUtils.FillData("", "F", 12);
        block4 = "";
        block4 = block4 + TokenUtils.ReverseData(meterID, 40);
        block4 = block4 + TokenUtils.ReverseData(customerID, 40);
        block4 = block4 + TokenUtils.ReverseData(utilityID, 12);
        checkSum = TokenUtils.getCheckSum(block4);
        checkSum = TokenUtils.ReverseData(checkSum, 4);
        block4 = blankAreaData + block4 + checkSum;
        pwdData = pwdData + "FFFFFFFFFFFF";
        block5 = "";
        block5 = block5 + pwdData.substring(6, 8);
        block5 = block5 + pwdData.substring(10, 12);
        block5 = block5 + pwdData.substring(8, 10);
        block5 = block5 + pwdData.substring(0, 2);
        block5 = block5 + pwdData.substring(4, 6);
        block5 = block5 + pwdData.substring(2, 4);
        checkSum = TokenUtils.getCheckSum(block5);
        checkSum = TokenUtils.ReverseData(checkSum, 4);
        block5 = block5 + checkSum;
        block6 = "";

        for(i = 0; i <= this.maxTokenNum - 1; ++i) {
            block6 = block6 + "FF";
        }

        block6 = block6 + TokenUtils.FillData("", "F", 12);
        block6 = block6 + TokenUtils.FillData("", "F", 8);
        checkSum = TokenUtils.getCheckSum(block6);
        checkSum = TokenUtils.ReverseData(checkSum, 4);
        block6 = block6 + checkSum;
        blankAreaData = TokenUtils.FillData("", "F", 6);
        block7 = "";
        block7 = block7 + blankAreaData;

        for(i = 0; i <= this.maxMonthNum - 1; ++i) {
            monthData = TokenUtils.FillData("", "F", 108);
            checkSum = TokenUtils.FillData("", "F", 4);
            block7 = block7 + monthData + checkSum;
        }

        eventData = TokenUtils.FillData("", "F", 52);
        checkSum = TokenUtils.FillData("", "F", 4);
        block7 = block7 + eventData + checkSum;
        blankAreaData = TokenUtils.FillData("", "F", 8);
        eventData = TokenUtils.FillData("", "F", 52);
        checkSum = TokenUtils.FillData("", "F", 4);
        block7 = block7 + blankAreaData + eventData + checkSum;
        blankAreaData = TokenUtils.FillData("", "F", 8);
        eventData = TokenUtils.FillData("", "F", 52);
        checkSum = TokenUtils.FillData("", "F", 4);
        block7 = block7 + blankAreaData + eventData + checkSum;
        blankAreaData = TokenUtils.FillData("", "F", 8);
        eventData = TokenUtils.FillData("", "F", 52);
        checkSum = TokenUtils.FillData("", "F", 4);
        block7 = block7 + blankAreaData + eventData + checkSum;
        blankAreaData = TokenUtils.FillData("", "F", 8);
        eventData = TokenUtils.FillData("", "F", 52);
        checkSum = TokenUtils.FillData("", "F", 4);
        block7 = block7 + blankAreaData + eventData + checkSum;
        blankAreaData = TokenUtils.FillData("", "F", 8);
        block8 = "";
        block8 = block8 + TokenUtils.FillData("", "F", 12);
        block8 = block8 + TokenUtils.FillData("", "F", 20);
        block8 = block8 + TokenUtils.FillData("", "F", 2);
        checkSum = TokenUtils.FillData("", "F", 4);
        block8 = blankAreaData + block8 + checkSum;
        blankAreaData = TokenUtils.FillData("", "F", 82);
        cardMap = block1 + block2 + block3 + block4 + block5 + block6 + block7 + block8 + blankAreaData;
        cardMap = cardMap.substring(8, cardMap.length());
        return cardMap;
    }

    public String decryptSmartCardReturnData(String meterNo, String sgc, int tariffIndex, int keyVersion, int keyExpiredTime, long keyNo, String encryptedData) {
        String rtnXML = "";
        String answerToReset = "";
        String binaryPattern = "";
        String version = "";
        String meterID = "";
        String customerID = "";
        String utilityID = "";
        String sanctionedLoad = "";
        String meterType = "";
        String lastRechargeAmount = "";
        String lastRechargeDate = "";
        String lastTransactionID = "";
        String cardType = "";
        String cardUsedFlag = "";
        String tokenTotalNum = "0";
        String meterID_Rtn = "";
        String customerID_Rtn = "";
        String utilityID_Rtn = "";
        String psDataA = "";
        String psDataB = "";
        String psDataC = "";
        String psDataD = "";
        String psDataE = "";
        String psDataF = "";
        String[] billingDate = new String[6];
        String[] activeEnergyImport = new String[6];
        String[] takaRecharged = new String[6];
        String[] takaUsed = new String[6];
        String[] activeMaximumPower = new String[6];
        String[] reactiveMaximumPower = new String[6];
        String[] activeEnergyImportT1 = new String[6];
        String[] activeEnergyImportT2 = new String[6];
        String[] reactiveEnergyImportT1 = new String[6];
        String[] reactiveEnergyImportT2 = new String[6];
        String[] totalChargeT1 = new String[6];
        String[] totalChargeT2 = new String[6];
        String[] numberOfPowerFailures = new String[6];
        String[] numberOfSanctionedLoadExceeded = new String[6];
        String[] monthAveragePowerFactor = new String[6];
        String[] tokens = new String[this.maxTokenNum];
        String[] tokensResult = new String[this.maxTokenNum];
        String rtnToken = "";
        String updateFlag = "";
        String dataValue = "";
        String checkSum = "";
        String blockData = "";
        String rtnBillingDate = "";
        String tokenList = "";
        String rtnTokenResultList = "";
        int addr = 0;
        int len = 4;
        answerToReset = encryptedData.substring(addr * 2, addr * 2 + len * 2);
        addr = 4;
        len = 2;
        binaryPattern = encryptedData.substring(addr * 2, addr * 2 + len * 2);
        binaryPattern = Integer.toString(Integer.parseInt(binaryPattern, 16));
        addr = 6;
        len = 1;
        version = encryptedData.substring(addr * 2, addr * 2 + len * 2);
        version = TokenUtils.ReverseData(version, len * 2);
        addr = 7;
        len = 10;
        meterID = encryptedData.substring(addr * 2, addr * 2 + len * 2);
        meterID = TokenUtils.ReverseData(meterID, len * 2);
        addr = 17;
        len = 10;
        customerID = encryptedData.substring(addr * 2, addr * 2 + len * 2);
        customerID = TokenUtils.ReverseData(customerID, len * 2);
        addr = 27;
        len = 6;
        utilityID = encryptedData.substring(addr * 2, addr * 2 + len * 2);
        utilityID = TokenUtils.ReverseData(utilityID, len * 2);
        addr = 33;
        len = 6;
        sanctionedLoad = encryptedData.substring(addr * 2, addr * 2 + len * 2);
        sanctionedLoad = TokenUtils.ReverseData(sanctionedLoad, len * 2);
        if (sanctionedLoad.toUpperCase().equals(TokenUtils.FillData("", "F", len * 2))) {
            sanctionedLoad = "0";
        } else {
            sanctionedLoad = Long.toString(Long.parseLong(sanctionedLoad));
        }

        addr = 39;
        len = 1;
        meterType = encryptedData.substring(addr * 2, addr * 2 + len * 2);
        meterType = Integer.toString(Integer.parseInt(meterType, 16));
        meterType = TokenUtils.FillData(meterType, "0", len * 2);
        addr = 42;
        len = 4;
        lastRechargeAmount = encryptedData.substring(addr * 2, addr * 2 + len * 2);
        lastRechargeAmount = TokenUtils.ReverseData(lastRechargeAmount, len * 2);
        lastRechargeAmount = Long.toString(Long.parseLong(lastRechargeAmount, 16));
        lastRechargeAmount = Double.toString(Double.parseDouble(lastRechargeAmount) / 100.0D);
        addr = 46;
        len = 3;
        lastRechargeDate = encryptedData.substring(addr * 2, addr * 2 + len * 2);
        addr = 49;
        len = 10;
        lastTransactionID = encryptedData.substring(addr * 2, addr * 2 + len * 2);
        addr = 100;
        len = 4;
        blockData = encryptedData.substring(addr * 2, addr * 2 + len * 2);
        addr = 104;
        len = 2;
        checkSum = encryptedData.substring(addr * 2, addr * 2 + len * 2);
        checkSum = TokenUtils.ReverseData(checkSum, 4);
        if (TokenUtils.getCheckSum(blockData).toUpperCase().equals(checkSum.toUpperCase())) {
            addr = 100;
            len = 2;
            cardType = encryptedData.substring(addr * 2, addr * 2 + len * 2);
            cardType = TokenUtils.ReverseData(cardType, len * 2);
            addr = 102;
            len = 1;
            cardUsedFlag = encryptedData.substring(addr * 2, addr * 2 + len * 2);
            addr = 103;
            len = 1;
            tokenTotalNum = encryptedData.substring(addr * 2, addr * 2 + len * 2);
            tokenTotalNum = TokenUtils.ReverseData(tokenTotalNum, len * 2);
            tokenTotalNum = Integer.toString(Integer.parseInt(tokenTotalNum, 16));
        }


        for(int i = 0; i <= this.maxTokenNum - 1; ++i) {
            tokens[i] = "";
        }

        addr = 112;
        len = 10;

        for(int i = 0; i <= this.maxTokenNum - 1; ++i) {
            dataValue = encryptedData.substring(addr * 2, addr * 2 + len * 2);
            if (dataValue.toUpperCase().equals("FFFFFFFFFFFFFFFFFFFF")) {
                break;
            }

            tokens[i] = dataValue;
            addr += len;
        }

        addr = 368;
        len = 46;
        blockData = encryptedData.substring(addr * 2, addr * 2 + len * 2);
        addr = 414;
        len = 2;
        checkSum = encryptedData.substring(addr * 2, addr * 2 + len * 2);
        checkSum = TokenUtils.ReverseData(checkSum, 4);
        if (TokenUtils.getCheckSum(blockData).toUpperCase().equals(checkSum.toUpperCase())) {
            addr = 368;
            len = 10;
            meterID_Rtn = encryptedData.substring(addr * 2, addr * 2 + len * 2);
            meterID_Rtn = TokenUtils.ReverseData(meterID_Rtn, len * 2);
            addr = 388;
            len = 10;
            customerID_Rtn = encryptedData.substring(addr * 2, addr * 2 + len * 2);
            customerID_Rtn = TokenUtils.ReverseData(customerID_Rtn, len * 2);
            addr = 408;
            len = 6;
            utilityID_Rtn = encryptedData.substring(addr * 2, addr * 2 + len * 2);
            utilityID_Rtn = TokenUtils.ReverseData(utilityID_Rtn, len * 2);
        }

        addr = 416;
        len = 6;
        blockData = encryptedData.substring(addr * 2, addr * 2 + len * 2);
        addr = 422;
        len = 2;
        checkSum = encryptedData.substring(addr * 2, addr * 2 + len * 2);
        checkSum = TokenUtils.ReverseData(checkSum, len * 2);
        psDataA = "FF";
        psDataB = "FF";
        psDataC = "FF";
        psDataD = "FF";
        psDataE = "FF";
        psDataF = "FF";
        if (TokenUtils.getCheckSum(blockData).toUpperCase().equals(checkSum.toUpperCase())) {
            addr = 416;
            len = 1;
            psDataD = encryptedData.substring(addr * 2, addr * 2 + len * 2);
            addr = 417;
            len = 1;
            psDataF = encryptedData.substring(addr * 2, addr * 2 + len * 2);
            addr = 418;
            len = 1;
            psDataE = encryptedData.substring(addr * 2, addr * 2 + len * 2);
            addr = 419;
            len = 1;
            psDataA = encryptedData.substring(addr * 2, addr * 2 + len * 2);
            addr = 420;
            len = 1;
            psDataC = encryptedData.substring(addr * 2, addr * 2 + len * 2);
            addr = 421;
            len = 1;
            psDataB = encryptedData.substring(addr * 2, addr * 2 + len * 2);
        }

        addr = 424;
        len = 35;
        blockData = encryptedData.substring(addr * 2, addr * 2 + len * 2);
        addr = 459;
        len = 2;
        checkSum = encryptedData.substring(addr * 2, addr * 2 + len * 2);
        checkSum = TokenUtils.ReverseData(checkSum, len * 2);

        for(int i = 0; i <= this.maxTokenNum - 1; ++i) {
            tokensResult[i] = "";
        }

        if (TokenUtils.getCheckSum(blockData).toUpperCase().equals(checkSum.toUpperCase()) && !tokenTotalNum.isEmpty()) {
            addr = 424;
            len = 1;

            for(int i = 0; i <= Integer.valueOf(tokenTotalNum) - 1; ++i) {
                dataValue = encryptedData.substring(addr * 2, addr * 2 + len * 2);
                tokensResult[i] = Integer.toString(TokenUtils.HexToInt(dataValue));
                addr += len;
            }

        }

        for(int i = 0; i <= Integer.valueOf(tokenTotalNum) - 1; ++i) {
            if (!tokensResult[i].equals("255")) {
                tokens[i] = "";
                tokensResult[i] = "";
            }

            if (!tokens[i].isEmpty()) {
                if (tokenList.isEmpty()) {
                    tokenList = tokens[i];
                } else {
                    tokenList = tokenList + "," + tokens[i];
                }
            }

            if (!tokensResult[i].isEmpty()) {
                if (rtnTokenResultList.isEmpty()) {
                    rtnTokenResultList = tokensResult[i];
                } else {
                    rtnTokenResultList = rtnTokenResultList + "," + tokensResult[i];
                }
            }
        }

        for(int i = 0; i <= this.maxMonthNum - 1; ++i) {
            billingDate[i] = "";
            activeEnergyImport[i] = "";
            takaRecharged[i] = "";
            takaUsed[i] = "";
            activeMaximumPower[i] = "";
            reactiveMaximumPower[i] = "";
            activeEnergyImportT1[i] = "";
            activeEnergyImportT2[i] = "";
            reactiveEnergyImportT1[i] = "";
            reactiveEnergyImportT2[i] = "";
            totalChargeT1[i] = "";
            totalChargeT2[i] = "";
            numberOfPowerFailures[i] = "";
            numberOfSanctionedLoadExceeded[i] = "";
            monthAveragePowerFactor[i] = "";
        }

        addr = 464;

        for(int i = 0; i <= this.maxMonthNum - 1; ++i) {
            len = 54;
            blockData = encryptedData.substring(addr * 2, addr * 2 + len * 2);
            checkSum = encryptedData.substring((addr + len) * 2, (addr + len) * 2 + 4);
            checkSum = TokenUtils.ReverseData(checkSum, 4);
            if (!TokenUtils.getCheckSum(blockData).toUpperCase().equals(checkSum.toUpperCase())) {
                len = 56;
                addr += len;
            } else {
                len = 6;
                dataValue = encryptedData.substring(addr * 2, addr * 2 + len * 2);
                if (!dataValue.toUpperCase().equals(TokenUtils.FillData("", "F", len * 2)) && !dataValue.toUpperCase().equals(TokenUtils.FillData("", "0", len * 2))) {
                    dataValue = "20" + dataValue;
                    rtnBillingDate = dataValue;
                } else {
                    dataValue = "";
                    rtnBillingDate = "";
                }

                billingDate[i] = dataValue;
                addr += len;
                len = 4;
                dataValue = encryptedData.substring(addr * 2, addr * 2 + len * 2);
                if (!dataValue.toUpperCase().equals(TokenUtils.FillData("", "F", len * 2)) && !rtnBillingDate.equals("")) {
                    dataValue = TokenUtils.ReverseData(dataValue, len * 2);
                    dataValue = Long.toString(Long.parseLong(dataValue, 16));
                    dataValue = Double.toString(Double.parseDouble(dataValue) / 100.0D);
                } else {
                    dataValue = "";
                }

                activeEnergyImport[i] = dataValue;
                addr += len;
                len = 4;
                dataValue = encryptedData.substring(addr * 2, addr * 2 + len * 2);
                if (!dataValue.toUpperCase().equals(TokenUtils.FillData("", "F", len * 2)) && !rtnBillingDate.equals("")) {
                    dataValue = TokenUtils.ReverseData(dataValue, len * 2);
                    dataValue = Long.toString(Long.parseLong(dataValue, 16));
                    dataValue = Double.toString(Double.parseDouble(dataValue) / 100.0D);
                } else {
                    dataValue = "";
                }

                takaRecharged[i] = dataValue;
                addr += len;
                len = 4;
                dataValue = encryptedData.substring(addr * 2, addr * 2 + len * 2);
                if (!dataValue.toUpperCase().equals(TokenUtils.FillData("", "F", len * 2)) && !rtnBillingDate.equals("")) {
                    dataValue = TokenUtils.ReverseData(dataValue, len * 2);
                    dataValue = Long.toString(Long.parseLong(dataValue, 16));
                    dataValue = Double.toString(Double.parseDouble(dataValue) / 100.0D);
                } else {
                    dataValue = "";
                }

                takaUsed[i] = dataValue;
                addr += len;
                len = 3;
                dataValue = encryptedData.substring(addr * 2, addr * 2 + len * 2);
                if (!dataValue.toUpperCase().equals(TokenUtils.FillData("", "F", len * 2)) && !rtnBillingDate.equals("")) {
                    dataValue = TokenUtils.ReverseData(dataValue, len * 2);
                    dataValue = Long.toString(Long.parseLong(dataValue, 16));
                    dataValue = Double.toString(Double.parseDouble(dataValue) / 10000.0D);
                } else {
                    dataValue = "";
                }

                activeMaximumPower[i] = dataValue;
                addr += len;
                len = 3;
                dataValue = encryptedData.substring(addr * 2, addr * 2 + len * 2);
                if (!dataValue.toUpperCase().equals(TokenUtils.FillData("", "F", len * 2)) && !rtnBillingDate.equals("")) {
                    dataValue = TokenUtils.ReverseData(dataValue, len * 2);
                    dataValue = Long.toString(Long.parseLong(dataValue, 16));
                    dataValue = Double.toString(Double.parseDouble(dataValue) / 10000.0D);
                } else {
                    dataValue = "";
                }

                reactiveMaximumPower[i] = dataValue;
                addr += len;
                len = 4;
                dataValue = encryptedData.substring(addr * 2, addr * 2 + len * 2);
                if (!dataValue.toUpperCase().equals(TokenUtils.FillData("", "F", len * 2)) && !rtnBillingDate.equals("")) {
                    dataValue = TokenUtils.ReverseData(dataValue, len * 2);
                    dataValue = Long.toString(Long.parseLong(dataValue, 16));
                    dataValue = Double.toString(Double.parseDouble(dataValue) / 100.0D);
                } else {
                    dataValue = "";
                }

                activeEnergyImportT1[i] = dataValue;
                addr += len;
                len = 4;
                dataValue = encryptedData.substring(addr * 2, addr * 2 + len * 2);
                if (!dataValue.toUpperCase().equals(TokenUtils.FillData("", "F", len * 2)) && !rtnBillingDate.equals("")) {
                    dataValue = TokenUtils.ReverseData(dataValue, len * 2);
                    dataValue = Long.toString(Long.parseLong(dataValue, 16));
                    dataValue = Double.toString(Double.parseDouble(dataValue) / 100.0D);
                } else {
                    dataValue = "";
                }

                activeEnergyImportT2[i] = dataValue;
                addr += len;
                len = 4;
                dataValue = encryptedData.substring(addr * 2, addr * 2 + len * 2);
                if (!dataValue.toUpperCase().equals(TokenUtils.FillData("", "F", len * 2)) && !rtnBillingDate.equals("")) {
                    dataValue = TokenUtils.ReverseData(dataValue, len * 2);
                    dataValue = Long.toString(Long.parseLong(dataValue, 16));
                    dataValue = Double.toString(Double.parseDouble(dataValue) / 100.0D);
                } else {
                    dataValue = "";
                }

                reactiveEnergyImportT1[i] = dataValue;
                addr += len;
                len = 4;
                dataValue = encryptedData.substring(addr * 2, addr * 2 + len * 2);
                if (!dataValue.toUpperCase().equals(TokenUtils.FillData("", "F", len * 2)) && !rtnBillingDate.equals("")) {
                    dataValue = TokenUtils.ReverseData(dataValue, len * 2);
                    dataValue = Long.toString(Long.parseLong(dataValue, 16));
                    dataValue = Double.toString(Double.parseDouble(dataValue) / 100.0D);
                } else {
                    dataValue = "";
                }

                reactiveEnergyImportT2[i] = dataValue;
                addr += len;
                len = 4;
                dataValue = encryptedData.substring(addr * 2, addr * 2 + len * 2);
                if (!dataValue.toUpperCase().equals(TokenUtils.FillData("", "F", len * 2)) && !rtnBillingDate.equals("")) {
                    dataValue = TokenUtils.ReverseData(dataValue, len * 2);
                    dataValue = Long.toString(Long.parseLong(dataValue, 16));
                    dataValue = Double.toString(Double.parseDouble(dataValue) / 100.0D);
                } else {
                    dataValue = "";
                }

                totalChargeT1[i] = dataValue;
                addr += len;
                len = 4;
                dataValue = encryptedData.substring(addr * 2, addr * 2 + len * 2);
                if (!dataValue.toUpperCase().equals(TokenUtils.FillData("", "F", len * 2)) && !rtnBillingDate.equals("")) {
                    dataValue = TokenUtils.ReverseData(dataValue, len * 2);
                    dataValue = Long.toString(Long.parseLong(dataValue, 16));
                    dataValue = Double.toString(Double.parseDouble(dataValue) / 100.0D);
                } else {
                    dataValue = "";
                }

                totalChargeT2[i] = dataValue;
                addr += len;
                len = 2;
                dataValue = encryptedData.substring(addr * 2, addr * 2 + len * 2);
                if (!dataValue.toUpperCase().equals(TokenUtils.FillData("", "F", len * 2)) && !rtnBillingDate.equals("")) {
                    dataValue = TokenUtils.ReverseData(dataValue, len * 2);
                    dataValue = Long.toString(Long.parseLong(dataValue, 16));
                } else {
                    dataValue = "";
                }

                numberOfPowerFailures[i] = dataValue;
                addr += len;
                len = 2;
                dataValue = encryptedData.substring(addr * 2, addr * 2 + len * 2);
                if (!dataValue.toUpperCase().equals(TokenUtils.FillData("", "F", len * 2)) && !rtnBillingDate.equals("")) {
                    dataValue = TokenUtils.ReverseData(dataValue, len * 2);
                    dataValue = Long.toString(Long.parseLong(dataValue, 16));
                } else {
                    dataValue = "";
                }

                numberOfSanctionedLoadExceeded[i] = dataValue;
                addr += len;
                len = 2;
                dataValue = encryptedData.substring(addr * 2, addr * 2 + len * 2);
                if (!dataValue.toUpperCase().equals(TokenUtils.FillData("", "F", len * 2)) && !rtnBillingDate.equals("")) {
                    dataValue = TokenUtils.ReverseData(dataValue, len * 2);
                    dataValue = Long.toString(Long.parseLong(dataValue, 16));
                    dataValue = Double.toString(Double.parseDouble(dataValue) / 1000.0D);
                } else {
                    dataValue = "";
                }

                monthAveragePowerFactor[i] = dataValue;
                addr += len;
                len = 2;
                addr += len;
            }
        }

        addr = 960;
        len = 17;
        blockData = encryptedData.substring(addr * 2, addr * 2 + len * 2);
        addr = 977;
        len = 2;
        checkSum = encryptedData.substring(addr * 2, addr * 2 + len * 2);
        checkSum = TokenUtils.ReverseData(checkSum, len * 2);
        if (TokenUtils.getCheckSum(blockData).toUpperCase().equals(checkSum.toUpperCase())) {
            addr = 966;
            len = 10;
            rtnToken = encryptedData.substring(addr * 2, addr * 2 + len * 2);
            rtnToken = TokenUtils.ReverseData(rtnToken, len * 2);
            addr = 976;
            len = 1;
            updateFlag = encryptedData.substring(addr * 2, addr * 2 + len * 2);
        }

        rtnXML = "";
        rtnXML = rtnXML + "<?xml version=\"1.0\" encoding=\"UTF-8\"?>";
        rtnXML = rtnXML + "<card>";
        rtnXML = rtnXML + "<block1>";
        rtnXML = rtnXML + "<answerToReset>" + answerToReset + "</answerToReset>";
        rtnXML = rtnXML + "<version>" + version + "</version>";
        rtnXML = rtnXML + "<meterID>" + meterID + "</meterID>";
        rtnXML = rtnXML + "<customerID>" + customerID + "</customerID>";
        rtnXML = rtnXML + "<utilityID>" + utilityID + "</utilityID>";
        rtnXML = rtnXML + "<sanctionedLoad>" + sanctionedLoad + "</sanctionedLoad>";
        rtnXML = rtnXML + "<meterType>" + meterType + "</meterType>";
        rtnXML = rtnXML + "<lastRechargeAmount>" + lastRechargeAmount + "</lastRechargeAmount>";
        rtnXML = rtnXML + "<lastRechargeDate>" + lastRechargeDate + "</lastRechargeDate>";
        rtnXML = rtnXML + "<lastTransactionID>" + lastTransactionID + "</lastTransactionID>";
        rtnXML = rtnXML + "</block1>";
        rtnXML = rtnXML + "<block2>";
        rtnXML = rtnXML + "<cardType>" + cardType + "</cardType>";
        rtnXML = rtnXML + "<cardUsedFlag>" + cardUsedFlag + "</cardUsedFlag>";
        rtnXML = rtnXML + "<tokenTotalNumber>" + tokenTotalNum + "</tokenTotalNumber>";
        rtnXML = rtnXML + "</block2>";
        rtnXML = rtnXML + "<block3>";
        rtnXML = rtnXML + "<token>" + tokenList + "</token>";
        rtnXML = rtnXML + "</block3>";
        rtnXML = rtnXML + "<block4>";
        rtnXML = rtnXML + "<meterID>" + meterID_Rtn + "</meterID>";
        rtnXML = rtnXML + "<consumerID>" + customerID_Rtn + "</consumerID>";
        rtnXML = rtnXML + "<utilityID>" + utilityID_Rtn + "</utilityID>";
        rtnXML = rtnXML + "</block4>";
        rtnXML = rtnXML + "<block5>";
        rtnXML = rtnXML + "<psData1>" + psDataA + "</psData1>";
        rtnXML = rtnXML + "<psData2>" + psDataB + "</psData2>";
        rtnXML = rtnXML + "<psData3>" + psDataC + "</psData3>";
        rtnXML = rtnXML + "<psData4>" + psDataD + "</psData4>";
        rtnXML = rtnXML + "<psData5>" + psDataE + "</psData5>";
        rtnXML = rtnXML + "<psData6>" + psDataF + "</psData6>";
        rtnXML = rtnXML + "</block5>";
        rtnXML = rtnXML + "<block6>";
        rtnXML = rtnXML + "<tokenReturnCode>" + rtnTokenResultList + "</tokenReturnCode>";
        rtnXML = rtnXML + "</block6>";
        rtnXML = rtnXML + "<block7>";

        for(int i = 0; i <= this.maxMonthNum - 1; ++i) {
            rtnXML = rtnXML + "<LastMonth" + Integer.toString(i + 1) + ">";
            rtnXML = rtnXML + "<billingDate>" + billingDate[i] + "</billingDate>";
            rtnXML = rtnXML + "<activeEnergyImport>" + activeEnergyImport[i] + "</activeEnergyImport>";
            rtnXML = rtnXML + "<takaRecharged>" + takaRecharged[i] + "</takaRecharged>";
            rtnXML = rtnXML + "<takaUsed>" + takaUsed[i] + "</takaUsed>";
            rtnXML = rtnXML + "<activeMaximumPower>" + activeMaximumPower[i] + "</activeMaximumPower>";
            rtnXML = rtnXML + "<reactiveMaximumPower>" + reactiveMaximumPower[i] + "</reactiveMaximumPower>";
            rtnXML = rtnXML + "<activeEnergyImportT1>" + activeEnergyImportT1[i] + "</activeEnergyImportT1>";
            rtnXML = rtnXML + "<activeEnergyImportT2>" + activeEnergyImportT2[i] + "</activeEnergyImportT2>";
            rtnXML = rtnXML + "<reactiveEnergyImportT1>" + reactiveEnergyImportT1[i] + "</reactiveEnergyImportT1>";
            rtnXML = rtnXML + "<reactiveEnergyImportT2>" + reactiveEnergyImportT2[i] + "</reactiveEnergyImportT2>";
            rtnXML = rtnXML + "<totalChargeT1>" + totalChargeT1[i] + "</totalChargeT1>";
            rtnXML = rtnXML + "<totalChargeT2>" + totalChargeT2[i] + "</totalChargeT2>";
            rtnXML = rtnXML + "<numberOfPowerFailures>" + numberOfPowerFailures[i] + "</numberOfPowerFailures>";
            rtnXML = rtnXML + "<numberOfSanctionedLoadExceeded>" + numberOfSanctionedLoadExceeded[i] + "</numberOfSanctionedLoadExceeded>";
            rtnXML = rtnXML + "<monthAveragePowerFactor>" + monthAveragePowerFactor[i] + "</monthAveragePowerFactor>";
            rtnXML = rtnXML + "</LastMonth" + Integer.toString(i + 1) + ">";
        }

        rtnXML = rtnXML + "</block7>";
        rtnXML = rtnXML + "<block8>";
        rtnXML = rtnXML + "<returnToken>" + rtnToken + "</returnToken>";
        rtnXML = rtnXML + "<updateFlag>" + updateFlag + "</updateFlag>";
        rtnXML = rtnXML + "</block8>";
        rtnXML = rtnXML + "</card>";
        return rtnXML;
    }
}
